package com.zhf.server;

import com.zhf.model.*;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 编程实现数据的存取
 */
public class ServerDao {
    // 定义两个文件地址分别用于存放学员和考题集合
    private static final String traineeListFile = "traineeListFile.txt";
    private static final String questionListFile = "questionFile.txt";
    private static final String examUserListFile = "examUserList.txt";
    ObjectInputStream trainOis;
    ObjectOutputStream trainOos;
    ObjectInputStream questionOis;
    ObjectOutputStream questionOos;
    ObjectInputStream examUserOis;
    ObjectOutputStream examUserOos;
    List<User> userListFromFile = new ArrayList<>();
    List<Question> questionListFromFile = new ArrayList<>();
    List<ExamUser> examUserListFromFile = new ArrayList<>();

    {
        File traineeFile = new File(traineeListFile);
        if(traineeFile.exists() && traineeFile.length() > 4){
            try {
                trainOis = new ObjectInputStream(new FileInputStream(traineeFile));
                userListFromFile =(List<User>) trainOis.readObject();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }else{
            try {
                traineeFile.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        File questionFile = new File(questionListFile);
        if(questionFile.exists() && questionFile.length() > 4){
            try {
                questionOis = new ObjectInputStream(new FileInputStream(questionFile));
                questionListFromFile = (List<Question>)questionOis.readObject();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }else{
            try {
                questionFile.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        File examUserFile = new File(examUserListFile);
        if(examUserFile.exists() && examUserFile.length() > 4){
            try {
                examUserOis = new ObjectInputStream(new FileInputStream(examUserFile));
                examUserListFromFile = (List<ExamUser>) examUserOis.readObject();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }else{
            try{
                if(!examUserFile.exists()){
                    examUserFile.createNewFile();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }

    private void inittrainOos(){
        //if(trainOos == null){
            try {
                trainOos = new ObjectOutputStream(new FileOutputStream(new File(traineeListFile)));
            } catch (IOException e) {
                e.printStackTrace();
            }
        //}
    }

    private void closeTrainOos(){
        if(trainOos != null){
            try {
                trainOos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private  void initQuestionOos(){
        // f(questionOos == null){
            try {
                questionOos = new ObjectOutputStream(new FileOutputStream(new File(questionListFile)));
            } catch (IOException e) {
                e.printStackTrace();
            }
        // }
    }

    private void  closeQuestionOos(){
        if(questionOos != null){
            try {
                questionOos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void initExamUserOos(){
        try{
            examUserOos = new ObjectOutputStream(new FileOutputStream(new File(examUserListFile)));
        }catch (IOException e){
            e.printStackTrace();
        }
    }

    private void closeExamUserOos(){
        if(examUserOos != null){
            try {
                examUserOos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 编程实现管理员账号和密码的校验并将结果返回出去
     * @param user
     * @return
     */
    public boolean serverManagerCheck(User user) {
        if ("admin".equals(user.getUserName()) && "123456".equals(user.getPassword())) {
            return true;
        }
        return false;
    }

    /**
     * 编程实现普通学员账号和密码的校验并将结果返回出去
     * @param user
     * @return
     */
    public boolean serverUserCheck(User user) {
        UserMessage userMessage = selectTrainee(user);
        if("fail".equals(userMessage.getType())){
            return false;
        }
        else{
            User user1 = userMessage.getUser();
            if(user.getPassword().equals(user1.getPassword())){
                return true;
            }
            return false;
        }
    }

    public List<User> listUser(){
        List<User> users = new ArrayList<>();
        users = userListFromFile;
        return users;
    }

    public UserMessage addTrainee(User user){
        // 通过对象流获取文件中的list对象
        UserMessage userMessage = new UserMessage();
        List<User> users = listUser();
        // 如果已经存在学员，先判断要新增的学员是否存在
        if(users == null || users.isEmpty()){
            // 直接往对象流中写入该对象
            ArrayList<User> usersList = new ArrayList<>();
            usersList.add(user);
            try {
                inittrainOos();
                List<User> collect = usersList.stream().map(e -> {
                    User u = new User();
                    u.setUserName(e.getUserName());
                    u.setPassword(e.getPassword());
                    return u;
                }).collect(Collectors.toList());
                trainOos.writeObject(collect);
                trainOos.flush();
                userMessage.setType("success");
                userMessage.setUser(user);
                if(userListFromFile == null) userListFromFile = new ArrayList<>();
                userListFromFile = usersList;
                System.out.println("服务器端添加学员" + user + "成功！");
                closeTrainOos();
                /*
                if(trainOis == null){
                    try {
                        trainOis = new ObjectInputStream(new FileInputStream(traineeListFile));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                 */
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        else {
            boolean b = users.stream().map(User::getUserName).noneMatch(userName -> user.getUserName().equals(userName));
            if(b){
                // 如果在已有学员中不存在该新增学员账号，则新增该学员
                users.add(user);
                try {
                    inittrainOos();
                    List<User> collect = users.stream().map(e -> {
                        User u = new User();
                        u.setUserName(e.getUserName());
                        u.setPassword(e.getPassword());
                        return u;
                    }).collect(Collectors.toList());
                    trainOos.writeObject(collect);
                    trainOos.flush();
                    userListFromFile = users;
                    userMessage.setType("success");
                    userMessage.setUser(user);
                    System.out.println("服务器端添加学员" + user + "成功！");
                    closeTrainOos();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }else{
                userMessage.setType("fail");
                userMessage.setUser(user);
            }
        }
        return userMessage;
    }

    public UserMessage selectTrainee(User user) {
        UserMessage userMessage = new UserMessage();
        List<User> userList = listUser();
        if(userList == null || userList.isEmpty()){
            userMessage.setType("fail");
            userMessage.setUser(user);
        }
        else{
            boolean b = userList.stream().map(User::getUserName).noneMatch(userName -> user.getUserName().equals(userName));
            if(b){
                userMessage.setType("fail");
                userMessage.setUser(user);
            }
            else{
                userMessage.setType("success");
                List<User> userList1 = userList.stream().filter(user1 -> user.getUserName().equals(user1.getUserName())).collect(Collectors.toList());
                userMessage.setUser(userList1.get(0));
            }
        }
        if("fail".equals(userMessage.getType())){
            System.out.println("查找学员信息失败！");
        }
        return userMessage;
    }

    public UserMessage deleteTrainee(User user) {
        UserMessage userMessage = new UserMessage();
        List<User> userList = listUser();
        if(userList == null || userList.isEmpty()){
            userMessage.setType("fail");
        }
        else{
            boolean b = userList.stream().map(User::getUserName).noneMatch(userName -> user.getUserName().equals(userName));
            if(b){
                userMessage.setType("fail");
            }
            else{
                userMessage.setType("success");
                List<User> userList1 = userList.stream().filter(user1 -> user.getUserName().equals(user1.getUserName())).collect(Collectors.toList());
                if(userList1 != null && userList1.size() > 0){
                    userList.removeAll(userList1);
                    inittrainOos();
                    try {
                        List<Object> collect = userList.stream().map(e -> {
                            User u = new User();
                            u.setUserName(e.getUserName());
                            u.setPassword(e.getPassword());
                            return u;
                        }).collect(Collectors.toList());
                        trainOos.writeObject(collect);
                        trainOos.flush();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    userListFromFile = userList;
                    closeTrainOos();
                }
            }
        }
        userMessage.setUser(user);
        return userMessage;
    }

    public UserUpdVo updateTrainee(UserUpdVo userUpdVo) {
        UserUpdVo userUpdVo1 = new UserUpdVo();
        User user = userUpdVo.getUserMessage().getUser();
        // 需要判断新的用户账号是否已经存在
        UserMessage userMessage = selectTrainee(user);
        if("success".equals(userMessage.getType())){
            userUpdVo1.setOriginUserAccount(userUpdVo.getOriginUserAccount());
            UserMessage userMessage1 = new UserMessage();
            userMessage1.setType("fail");
            userMessage1.setUser(userUpdVo.getUserMessage().getUser());
            userUpdVo1.setUserMessage(userMessage1);
            return userUpdVo1;
        }
        String originUserAccount = userUpdVo.getOriginUserAccount();
        // 获取原来学员对象
        List<User> userList = listUser();
        if(userList == null || userList.isEmpty()){
            userUpdVo1.setOriginUserAccount(originUserAccount);
            UserMessage userMessage1 = new UserMessage();
            userMessage1.setUser(user);
            userMessage1.setType("fail");
            userUpdVo1.setUserMessage(userMessage1);
            return  userUpdVo1;
        }
        List<User> userList1 = userList.stream().filter(user11 -> originUserAccount.equals(user11.getUserName())).collect(Collectors.toList());
        User originUser = userList1.get(0);
        originUser.setUserName(user.getUserName());
        originUser.setPassword(user.getPassword());
        try {
            inittrainOos();
            List<Object> collect = userList.stream().map(e -> {
                User u = new User();
                u.setUserName(e.getUserName());
                u.setPassword(e.getPassword());
                return u;
            }).collect(Collectors.toList());
            trainOos.writeObject(collect);
            trainOos.flush();
            userUpdVo1.setOriginUserAccount(originUserAccount);
            UserMessage userMessage1 = new UserMessage();
            userMessage1.setUser(user);
            userMessage1.setType("success");
            userUpdVo1.setUserMessage(userMessage1);
            userListFromFile = userList;
            closeTrainOos();
            return  userUpdVo1;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return  userUpdVo1;
    }

    public List<Question> listQuestion(){
        List<Question> questions = new ArrayList<>();
        /*try {
            questions = (List<Question>) questionOis.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }*/
        questions = questionListFromFile;
        return questions;
    }

    public QuestionMessage selectQuestion(Question question) {
        QuestionMessage questionMessage = new QuestionMessage();
        List<Question> questionList = listQuestion();
        if(questionList == null || questionList.isEmpty()){
            questionMessage.setMessage("fail");
            questionMessage.setQuestion(question);
        }
        else{
            List<Question> questionList1 = questionList.stream().filter(question1 -> question.getQuestionName().equals(question1.getQuestionName())).collect(Collectors.toList());
            if(questionList1 == null || questionList1.isEmpty()){
                questionMessage.setMessage("fail");
                questionMessage.setQuestion(question);
            }else {
                questionMessage.setMessage("success");
                questionMessage.setQuestion(questionList1.get(0));
            }
        }
        return questionMessage;
    }

    public QuestionMessage addQuestion(Question question){
        QuestionMessage questionMessage = new QuestionMessage();
        List<Question> questionList = listQuestion();
        if(questionList == null || questionList.isEmpty()){
            List<Question> questions = new ArrayList<>();
            questions.add(question);
            try {
                initQuestionOos();
                List<Question> collect = questions.stream().map(e -> {
                    Question q = new Question();
                    q.setQuestionName(e.getQuestionName());
                    q.setOptionA(e.getOptionA());
                    q.setOptionB(e.getOptionB());
                    q.setOptionC(e.getOptionC());
                    q.setOptionD(e.getOptionD());
                    q.setAnswer(e.getAnswer());
                    return q;
                }).collect(Collectors.toList());
                questionOos.writeObject(collect);
                questionOos.flush();
                questionMessage.setMessage("success");
                questionMessage.setQuestion(question);
                /*if(questionOis == null){
                    questionOis = new ObjectInputStream(new FileInputStream(questionListFile));
                }*/
                questionListFromFile = questions;
                closeQuestionOos();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        else{
            boolean b = questionList.stream().map(Question::getQuestionName).noneMatch(questionName -> question.getQuestionName().equals(questionName));
            if(b){
                questionList.add(question);
                try {
                    initQuestionOos();
                    List<Question> collect = questionList.stream().map(e -> {
                        Question q = new Question();
                        q.setQuestionName(e.getQuestionName());
                        q.setOptionA(e.getOptionA());
                        q.setOptionB(e.getOptionB());
                        q.setOptionC(e.getOptionC());
                        q.setOptionD(e.getOptionD());
                        q.setAnswer(e.getAnswer());
                        return q;
                    }).collect(Collectors.toList());
                    questionOos.writeObject(collect);
                    questionOos.flush();
                    questionMessage.setMessage("success");
                    questionMessage.setQuestion(question);
                    questionListFromFile = questionList;
                    closeQuestionOos();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            else{
                questionMessage.setMessage("fail");
                questionMessage.setQuestion(question);
            }
        }
        return questionMessage;
    }

    public QuestionMessage deleteQuestion(Question question){
        QuestionMessage questionMessage = new QuestionMessage();
        List<Question> questions = listQuestion();
        if(questions == null || questions.isEmpty()){
            questionMessage.setMessage("fail");
        }
        else{
            questionMessage.setMessage("success");
            List<Question> questions1 = questions.stream().filter(question1 -> question.getQuestionName().equals(question1.getQuestionName())).collect(Collectors.toList());
            if(questions1 != null && questions.size() > 0){
                questions.removeAll(questions1);
                try {
                    initQuestionOos();
                    List<Question> collect = questions.stream().map(e -> {
                        Question q = new Question();
                        q.setQuestionName(e.getQuestionName());
                        q.setOptionA(e.getOptionA());
                        q.setOptionB(e.getOptionB());
                        q.setOptionC(e.getOptionC());
                        q.setOptionD(e.getOptionD());
                        q.setAnswer(e.getAnswer());
                        return q;
                    }).collect(Collectors.toList());
                    questionOos.writeObject(collect);
                    questionOos.flush();
                    closeQuestionOos();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                questionListFromFile = questions;
            }
        }
        questionMessage.setQuestion(question);
        return questionMessage;
    }

    public QuestionUpdVo updateQuestion(QuestionUpdVo questionUpdVo){
        QuestionUpdVo questionUpdVo1 = new QuestionUpdVo();
        Question question = questionUpdVo.getQuestionMessage().getQuestion();
        // 需要判断修改后的考题是否已经存在
        QuestionMessage questionMessage = selectQuestion(question);
        if("success".equals(questionMessage.getMessage())){
            questionUpdVo1.setOriginQuestionName(questionUpdVo.getOriginQuestionName());
            QuestionMessage questionMessage1 = new QuestionMessage();
            questionMessage1.setQuestion(question);
            questionMessage1.setMessage("fail");
            questionUpdVo1.setQuestionMessage(questionMessage1);
            return questionUpdVo1;
        }
        String originQuestionName = questionUpdVo.getOriginQuestionName();
        List<Question> questions = listQuestion();
        if(questions == null || questions.isEmpty()){
            questionUpdVo1.setOriginQuestionName(originQuestionName);
            QuestionMessage questionMessage1 = new QuestionMessage();
            questionMessage1.setMessage("fail");
            questionMessage1.setQuestion(question);
            questionUpdVo1.setQuestionMessage(questionMessage1);
            return questionUpdVo1;
        }
        List<Question> questions1 = questions.stream().filter(question1 -> originQuestionName.equals(question1.getQuestionName())).collect(Collectors.toList());
        Question originQuestion = questions1.get(0);
        originQuestion.setQuestionName(question.getQuestionName());
        originQuestion.setOptionA(question.getOptionA());
        originQuestion.setOptionB(question.getOptionB());
        originQuestion.setOptionC(question.getOptionC());
        originQuestion.setOptionD(question.getOptionD());
        originQuestion.setAnswer(question.getAnswer());
        try {
            initQuestionOos();
            List<Question> collect = questions.stream().map(e -> {
                Question q = new Question();
                q.setQuestionName(e.getQuestionName());
                q.setOptionA(e.getOptionA());
                q.setOptionB(e.getOptionB());
                q.setOptionC(e.getOptionC());
                q.setOptionD(e.getOptionD());
                q.setAnswer(e.getAnswer());
                return q;
            }).collect(Collectors.toList());
            questionOos.writeObject(collect);
            questionOos.flush();
            questionUpdVo1.setOriginQuestionName(originQuestionName);
            QuestionMessage questionMessage1 = new QuestionMessage();
            questionMessage1.setMessage("success");
            questionMessage1.setQuestion(question);
            questionUpdVo1.setQuestionMessage(questionMessage1);
            questionListFromFile = questions;
            closeQuestionOos();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return questionUpdVo1;
    }

    public QuestionImportVo importQuestion(List<Question> questions) {
        QuestionImportVo questionImportVo = new QuestionImportVo();
        List<Question> questionList = listQuestion();
        if(questionList == null || questionList.isEmpty()){
            // 直接导入
            List<Question> questionList1 = new ArrayList<>();
            questionList1.addAll(questions);
            try {
                initQuestionOos();
                List<Question> collect = questionList1.stream().map(e -> {
                    Question q = new Question();
                    q.setQuestionName(e.getQuestionName());
                    q.setOptionA(e.getOptionA());
                    q.setOptionB(e.getOptionB());
                    q.setOptionC(e.getOptionC());
                    q.setOptionD(e.getOptionD());
                    q.setAnswer(e.getAnswer());
                    return q;
                }).collect(Collectors.toList());
                questionOos.writeObject(collect);
                questionOos.flush();
                questionImportVo.setMessage("success");
                questionImportVo.setQuestions(questions);
                /*if(questionOis == null){
                    questionOis = new ObjectInputStream(new FileInputStream(questionListFile));
                }*/
                questionListFromFile = questionList1;
                closeQuestionOos();
                return questionImportVo;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        else{
            boolean b = questionList.stream().noneMatch(question -> questions.stream().map(Question::getQuestionName).anyMatch(questionRequestName -> questionRequestName.equals(question.getQuestionName())));
            if(b){
                // 在已存在的试题库里面不存在要导入的题目，则代表可以导入
                questionList.addAll(questions);
                try {
                    initQuestionOos();
                    List<Question> collect = questionList.stream().map(e -> {
                        Question q = new Question();
                        q.setQuestionName(e.getQuestionName());
                        q.setOptionA(e.getOptionA());
                        q.setOptionB(e.getOptionB());
                        q.setOptionC(e.getOptionC());
                        q.setOptionD(e.getOptionD());
                        q.setAnswer(e.getAnswer());
                        return q;
                    }).collect(Collectors.toList());
                    questionOos.writeObject(collect);
                    questionOos.flush();
                    questionImportVo.setMessage("success");
                    questionImportVo.setQuestions(questions);
                    questionListFromFile = questionList;
                    closeQuestionOos();
                    return questionImportVo;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            else{
                questionImportVo.setMessage("fail");
                questionImportVo.setQuestions(questions);
                return questionImportVo;
            }
        }
        return questionImportVo;
    }

    public UserPasswordMessage updateTraineePassword(UserPassword userPassword) {
        UserPasswordMessage userPasswordMessage = new UserPasswordMessage();
        userPasswordMessage.setUserPassword(userPassword);
        List<User> userList = listUser();
        List<User> collect = userList.stream().filter(t -> userPassword.getUserName().equals(t.getUserName())).collect(Collectors.toList());
        if(collect.size() > 0){
            User user = collect.get(0);
            user.setPassword(userPassword.getNewPassword());
        }
        try {
            inittrainOos();
            List<User> collect1 = userList.stream().map(e -> {
                User u = new User();
                u.setUserName(e.getUserName());
                u.setPassword(e.getPassword());
                return u;
            }).collect(Collectors.toList());
            trainOos.writeObject(collect1);
            trainOos.flush();
            userPasswordMessage.setMessage("success");
            closeTrainOos();
            return userPasswordMessage;
        } catch (IOException e) {
            e.printStackTrace();
        }
        userPasswordMessage.setMessage("fail");
        return userPasswordMessage;
    }

    public List<ExamUser> listExamUser(){
        return examUserListFromFile.stream().map(e -> {
            ExamUser examUser = new ExamUser();
            examUser.setUser(e.getUser());
            examUser.setExamName(e.getExamName());
            examUser.setQuestions(e.getQuestions());
            examUser.setGrade(e.getGrade());
            return examUser;
        }).collect(Collectors.toList());
    }

    public ExamUserMessage selectExamUserByExamNameAndUser(ExamUser examUser){
        ExamUserMessage examUserMessage = new ExamUserMessage();
        List<ExamUser> examUsers = listExamUser();
        if(examUsers == null || examUsers.isEmpty()){
            // 如果考试系统还没有学院考试信息，则直接提示查询失败
            examUserMessage.setExamUser(examUser);
            examUserMessage.setMessage("fail");
        }
        else{
            List<ExamUser> collect = examUsers.stream().filter(e -> examUser.getExamName().equals(e.getExamName()) && examUser.getUser().getUserName().equals(e.getUser().getUserName())).collect(Collectors.toList());
            if(collect != null && !collect.isEmpty()){
                // 如果该用户对应考试名字已经存在，则查询成功
                examUserMessage.setExamUser(collect.get(0));
                examUserMessage.setMessage("success");
            }
            else{
                examUserMessage.setExamUser(examUser);
                examUserMessage.setMessage("fail");
            }
        }
        return examUserMessage;
    }

    public boolean saveExamUser(ExamUser examUser) {
        boolean isSaved = false;
        try{
            List<ExamUser> examUsers = listExamUser();
            if(examUsers == null) examUsers = new ArrayList<>();
            examUsers.add(examUser);
            List<Object> collect = examUsers.stream().map(e -> {
                ExamUser examUser1 = new ExamUser();
                examUser1.setUser(e.getUser());
                examUser1.setExamName(e.getExamName());
                examUser1.setQuestions(e.getQuestions());
                examUser1.setGrade(e.getGrade());
                return examUser1;
            }).collect(Collectors.toList());
            initExamUserOos();
            examUserOos.writeObject(collect);
            examUserOos.flush();
            examUserListFromFile = examUsers;
            isSaved = true;
            closeExamUserOos();
        }catch(Exception e){
            isSaved = false;
        }
        return isSaved;
    }

    public ExamUserListMessage selectExamUserListByUser(User user) {
        ExamUserListMessage examUserListMessage = new ExamUserListMessage();
        List<ExamUser> examUsers = listExamUser();
        if(examUsers == null || examUsers.isEmpty()){
            examUserListMessage.setMessage("fail");
        }
        List<ExamUser> collect = examUsers.stream().filter(e -> user.getUserName().equals(e.getUser().getUserName())).collect(Collectors.toList());
        if(collect == null || collect.isEmpty()){
            examUserListMessage.setMessage("fail");
        }
        else{
            examUserListMessage.setMessage("success");
            examUserListMessage.setExamUserList(collect);
        }
        return examUserListMessage;
    }
}
